﻿/////////////////////////////////////////////////////////////////////////////////
//
// InstantCube
// - Automatically generates Analysis Services cubes
// (C) Copyright Johan Åhlén 2009
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
// See the GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
//
// More info on InstantCube website: http://instantcube.codeplex.com
//
/////////////////////////////////////////////////////////////////////////////////


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace AdvantIQ.InstantCube.Model
{
    public class CubeMeasureGroup
    {
        public string ID { get; set; }
        public CubeMeasures Measures { get; set; }
        public CubeDimensions Dimensions { get; set; }
        public CubeSampleData SampleData { get; set; }

        private Project project;

        public CubeMeasureGroup(XElement srcNode, Project project)
        {
            try
            {
                this.project = project;

                ID = srcNode.Attribute("id").Value;
                if (string.IsNullOrEmpty(ID))
                    ID = "MeasureGroup";
                Measures = new CubeMeasures(srcNode.Element("measures"));
                Dimensions = new CubeDimensions(srcNode.Element("cubeDimensions"));
                SampleData = new CubeSampleData(srcNode.Element("sampleData"));
            }
            catch (ModelErrorException ex)
            {
                throw new ModelErrorException(this, ex);
            }
            catch (Exception ex)
            {
                throw new ModelErrorException(this, ex.Message);
            }
        }

        public override string ToString()
        {
            if (ID != null)
                return string.Format("MeasureGroup({0})", ID);
            else
                return "MeasureGroup";
        }

        public string GetTableName()
        {
            return project.Namings.FactPrefix + ID;
        }

        public List<FieldInfo> GetFields()
        {
            var lst = new List<FieldInfo>();
            lst.Add(new FieldInfo(GetPrimaryKey(),
                FieldType.SurrogateKey,
                project
            ));

            lst.AddRange(Measures.Select(m => new FieldInfo(m.ID, FieldType.Fact, m.Type, "" )));
            foreach (var dimensionRef in Dimensions)
            {
                var fieldName = dimensionRef.Alias != null && dimensionRef.Alias.Length > 0 ?
                    dimensionRef.Alias : project.Dimensions[dimensionRef.ID].GetPrimaryKey();
                lst.Add(new FieldInfo(fieldName, FieldType.ForeignKey, project ));
            }

            return lst;
        }

        public List<ForeignKey> GetForeignKeys()
        {
            var lst = new List<ForeignKey>();

            foreach (var dimensionRef in Dimensions)
            {
                var dimension = project.Dimensions[dimensionRef.ID];
                var fieldName = !string.IsNullOrEmpty(dimensionRef.Alias) ?
                    dimensionRef.Alias : dimension.GetPrimaryKey();
                lst.Add(new ForeignKey()
                {
                    ID = "FK_" + GetTableName() + "_" + fieldName,
                    LocalField = fieldName,
                    RemoteTable = dimension.GetTableName(),
                    RemoteField = dimension.GetPrimaryKey()
                });
            }

            return lst;
        }

        public string GetPrimaryKey()
        {
            return GetTableName() + "ID";
        }

        public List<string> GetWriteableFields()
        {
            return GetFields().Skip(1).Select(f => f.ID).ToList();
        }
    }
}
